#pragma once

#include <iostream>
#include <string>
#include <pthread.h>
#include <fstream>
#include <sstream>
#include <vector>
#include <sys/types.h>
#include <sys/socket.h>
#include "Socket.hpp"
#include "Log.hpp"

static const int defaultport = 8080;
const std::string wwwroot = "./wwwroot";
const std::string sep = "\r\n";
const std::string homepage = "index.html";

class HttpServer;

class ThreadDate
{
public:
    ThreadDate(int sockfd):_sockfd(sockfd){}
    int _sockfd;
};

class HttpRequest
{
public:
    void Deserialize(std::string req)
    {
        while(true)
        {
            std::size_t pos = req.find(sep);
            if(pos == std::string::npos) break;
            std::string temp = req.substr(0, pos);
            if(temp.empty()) break;
            req_header.push_back(temp);
            req.erase(0,pos+sep.size());
        }
        text = req;
    }

    void Parse()
    {
        std::stringstream ss(req_header[0]);
        ss >> method >> url >>http_version;
        file_path = wwwroot;
        if(url == "/" || url == "./index.html") file_path += "/" + homepage;
        else file_path += url;

    }

    void DebugPrintf()
    {
        for(auto& line: req_header)
        {
            std::cout << "-----------------------------------------" << std::endl;
            std::cout << line << std::endl;
        }
        std::cout << "method: " << method << std::endl;
        std::cout << "url: " << url << std::endl;
        std::cout << "http_version: " << http_version << std::endl;
        std::cout << "file_path: " << file_path << std::endl;
        std::cout << text << std::endl;
    }
public:
    std::vector<std::string> req_header;
    std::string text;

    //解析之后的结果
    std::string method;
    std::string url;
    std::string http_version; 
    std::string file_path;
};


class HttpServer
{
public:
    HttpServer(uint16_t port = defaultport):_port(port)
    {}

    bool Start()
    {
        _listensock.Socket();
        _listensock.Bind(_port);
        _listensock.Listen();
        while(true)
        {
            //获取客户端的信息
            std::string clientip;
            uint16_t clientport;
            int sockfd = _listensock.Accept(clientip, clientport);
            if(sockfd < 0) continue;
            lg(Info,"get a new link connect, sockfd: %d", sockfd);
            ThreadDate* td = new ThreadDate(sockfd);
            pthread_t tid;
            pthread_create(&tid, nullptr, ThreadRun, td);
        }   
    }

    static::std::string ReadHtmlContent(const std::string& htmlpath)
    {
        std::ifstream in(htmlpath);
        if(!in.is_open()) return "404";

        std::string content;
        std::string line;
        while(std::getline(in,line))
        {
            content += line;
        }

        in.close();
        return content;
    }

    static void HandlerHttp(int sockfd)
    {
        char buffer[10240];
        ssize_t n = recv(sockfd,buffer, sizeof(buffer), 0);
        if(n > 0)
        {
            buffer[n] = 0;
            std::cout << buffer;//假设我们读到了一个完整的http

            HttpRequest req;
            req.Deserialize(buffer);
            req.Parse();
            req.DebugPrintf();

            // std::string url = "a/b/c";
            // std::string path = wwwroot + url;

            //返回响应过程
            std::string text = ReadHtmlContent(req.file_path);
            std::string response_line ="HTTP/1.0 200 OK\r\n";
            std::string block_line = "\r\n";
            std::string response_header = "Content-Length: " + std::to_string(text.size()) + "\r\n";
            std::string response = response_line + response_header + block_line + text;

            send(sockfd,response.c_str(), response.size(),0);
        }
        close(sockfd);
    }

    static void* ThreadRun(void* args)
    {
        pthread_detach(pthread_self());
        ThreadDate* td = static_cast<ThreadDate*>(args);
        HandlerHttp(td->_sockfd);
        delete td;
        return nullptr;
    }

    ~HttpServer(){}
private:
    uint16_t _port;
    Sock _listensock;
};